package com.angel.mongodb.utils;

import com.angel.mongodb.annotation.QueryField;
import com.angel.mongodb.annotation.QueryType;
import com.angel.mongodb.annotation.SortField;
import com.angel.mongodb.entity.Page;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

public class Wraps<T> {
    /**
     * @Author gankench@gmail.com
     * @Description 〈true 传入空字符串("")时， 视为： 取消字段〉
     * 〈false 传入空字符串("")时， 视为： 字段名 = ""〉
     * @Date 3:48 PM 3/30/21
     * @Param
     * @return
     **/
    public static boolean skipEmpty = true;


    private <T> Wraps() {
        // ignore
    }

    public static <T> CriteriaAndWrapper<T> andWrapper() {
        return new CriteriaAndWrapper<T>();
    }

    public static <T> CriteriaWrapper andWrapper(T enity) {
        CriteriaWrapper criteriaWrapper = new CriteriaAndWrapper();
        criteriaWrapper.setList(buildCriterias(enity));
        return criteriaWrapper;
    }

    public static <T> CriteriaOrWrapper<T> orWrapper() {
        return new CriteriaOrWrapper<T>();
    }

    public static <T> CriteriaWrapper orWrapper(T enity) {
        CriteriaWrapper criteriaWrapper = new CriteriaOrWrapper();
        criteriaWrapper.setList(buildCriterias(enity));
        return criteriaWrapper;
    }

    /**
     * 根据vo构建查询条件Query
     *
     * @param enity
     * @param page
     * @return
     */
    public static <T> Query buildBasePageQuery(T enity, Page<T> page) {
        Query query = buildBaseQuery(enity);
        if (page != null) {
            // 查询page
            query.skip((page.getPageNum() - 1) * page.getPageSize());// 从那条记录开始
            query.limit(page.getPageSize());// 取多少条记录

            if (!query.isSorted()) {
                query.with(Sort.by(Sort.Direction.DESC, "id"));
            }
        }
        return query;
    }


    /**
     * 根据vo构建查询条件Query
     *
     * @param object
     * @return
     */
    public static Query buildBaseQuery(Object object) {
        Query query = new Query();

        Field[] fields = object.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            try {
                Object value = field.get(object);
                if (value != null) {
                    if ("serialversionuid".equals(field.getName().toLowerCase())) {
                        continue;
                    }
                    QueryField queryField = field.getAnnotation(QueryField.class);
                    if (queryField != null) {
                        if (QueryType.NOTQUERY.equals(queryField.type())) {
                            continue;
                        }
                        query.addCriteria(queryField.type().buildCriteria(queryField, field, value));
                    } else {
                        query.addCriteria(Criteria.where(field.getName()).is(value));
                    }
                }
                SortField sortField = field.getAnnotation(SortField.class);
                if (sortField != null) {
                    query.with(sortField.sort().buildSort(sortField, field));
                }
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return query;
    }

    /**
     * 根据object构建更新条件Query
     *
     * @param object
     * @return
     */
    public Update buildBaseUpdate(Object object) {
        Update update = new Update();

        Field[] fields = object.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            try {
                Object value = field.get(object);
                if (value != null) {
                    if ("id".equals(field.getName().toLowerCase()) || "serialversionuid".equals(field.getName().toLowerCase())) {
                        continue;
                    }
                    update.set(field.getName(), value);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return update;
    }

    private static List<Criteria> buildCriterias(Object object) {
        List<Criteria> criterias = new ArrayList<>();
        Field[] fields = object.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            try {
                Object value = field.get(object);
                if (value != null) {
                    if ("id".equals(field.getName().toLowerCase()) || "serialversionuid".equals(field.getName().toLowerCase())) {
                        continue;
                    }
                    QueryField queryField = field.getAnnotation(QueryField.class);
                    if (queryField != null) {
                        criterias.add(queryField.type().buildCriteria(queryField, field, value));
                    }
                }
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return criterias;
    }
//    private static CriteriaWrapper replace(CriteriaWrapper criteriaWrapper, Object source) {
//        if (source == null) {
//            return null;
//        }
//        Object target = source;
//
//        Class<?> srcClass = source.getClass();
//        Field[] fields = ReflectUtil.getFields(srcClass);
//        for (Field field : fields) {
//            Object classValue = ReflectUtil.getFieldValue(source, field);
//            if (classValue == null) {
//                continue;
//            }
//            //final 和 static 字段跳过
//            if (Modifier.isFinal(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) {
//                continue;
//            }
//
//            if (field.getType().equals(String.class)) {
//                String srcValue = (String) classValue;
//                if (skipEmpty) {
//                    if (StrUtil.isBlank(srcValue)) {
//                        continue;
//                    } else {
//                        criteriaWrapper.eq(ReflectUtil.getFieldName(field), srcValue);
//                    }
//                } else {
//                    criteriaWrapper.eq(ReflectUtil.getFieldName(field), srcValue);
//                }
//            } else if (field.getType().equals(List.class)) {
//                List srcValue = (List) classValue;
//                if (skipEmpty) {
//                    if (srcValue.isEmpty()) {
//                        continue;
//                    } else {
//                        criteriaWrapper.in(ReflectUtil.getFieldName(field), srcValue);
//                    }
//                } else {
//                    criteriaWrapper.in(ReflectUtil.getFieldName(field), srcValue);
//                }
//            }
//
//        }
//        return criteriaWrapper;
//    }

}
